package functions

import (
	"bytes"
	"encoding/json"
	"strings"

	"github.com/spf13/cast"

	"github.com/zfd81/rooster/util"
)

func Concat(strs ...interface{}) string {
	var buf bytes.Buffer
	for _, str := range strs {
		buf.WriteString(cast.ToString(str))
	}
	return buf.String()
}

func Lower(str string) string {
	return strings.ToLower(str)
}

func Upper(str string) string {
	return strings.ToUpper(str)
}

func Left(str string, length int) string {
	if str == "" || length < 0 {
		return ""
	}
	strRune := []rune(str)
	if length < len(strRune) {
		return string(strRune[:length])
	} else {
		return str
	}
}

func Right(str string, length int) string {
	if str == "" || length < 0 {
		return ""
	}
	strRune := []rune(str)
	strLen := len(strRune)
	if length < strLen {
		return string(strRune[strLen-length:])
	} else {
		return str
	}
}

func Lpad(str string, length int, padstr string) string {
	return util.Lpad(str, length, padstr)
}

func Rpad(str string, length int, padstr string) string {
	return util.Rpad(str, length, padstr)
}

func Ltrim(str string) string {
	return strings.TrimLeft(str, " ")
}

func Rtrim(str string) string {
	return strings.TrimRight(str, " ")
}

func Trim(str string) string {
	return strings.TrimSpace(str)
}

func Replace(str, old, new string) string {
	return strings.ReplaceAll(str, old, new)
}

func Strcmp(str1, str2 interface{}) int {
	if str1 == nil {
		str1 = ""
	}
	if str2 == nil {
		str2 = ""
	}
	return strings.Compare(cast.ToString(str1), cast.ToString(str2))
}

func Repeat(str string, count int) string {
	return strings.Repeat(str, count)
}

func Length(str string) int {
	return len(([]rune(str)))
}

func Reverse(val interface{}) string {
	var runes []rune
	str, ok := val.(string)
	if ok {
		runes = []rune(str)
	} else {
		runes = []rune(cast.ToString(val))
	}
	i := 0
	j := len(runes) - 1
	for i < j {
		runes[i], runes[j] = runes[j], runes[i]
		i++
		j--
	}
	return string(runes)
}

func Insert(str string, position int, length int, instr string) string {
	if position > 0 {
		position--
	}
	newstr := str[0:position] + instr
	if pos := position + length; pos < len(str) {
		newstr = newstr + str[position+length:]
	}
	return newstr
}

func Substr(str string, position int, length int) string {
	strRune := []rune(str)
	if position > len(strRune) {
		return ""
	} else if position > 0 {
		return Left(string(strRune[position-1:]), length)
	} else if (0 - position) <= len(strRune) {
		return Left(string(strRune[position+len(strRune):]), length)
	}
	return ""
}

func Split(str, sep string) []string {
	return strings.Split(str, sep)
}

func SplitN(str, sep string, n int) []string {
	return strings.SplitN(str, sep, n)
}

func Object(str string) map[string]interface{} {
	var m map[string]interface{}
	err := json.Unmarshal([]byte(str), &m)
	if err != nil {
		throwException("JSON format error")
	}
	return m
}
